const crypto = require("crypto");
const { GXH_ReplyCDATA } = require("../gzhConst");
const CryptoJS = require("crypto-js");
const GZHConfig = require("../gzhConfig");
const { DataSynthesizer } = require("utils");
const { xmlWithCDATA } = require("../tool/xmlWithCDATA");

const paddingAction = (buf) => {
    // 这里是 32个 字节??
    const blockSize = 32;
    const textLength = buf.length;
    // 计算需要填充的位数
    const amountToPad = blockSize - (textLength % blockSize);
    const result = Buffer.alloc(amountToPad);
    result.fill(amountToPad);
    return Buffer.concat([buf, result]);
};

function encode(contentObj, appId, nonce) {
    // 16个字节的 随机字符串
    let random = Buffer.alloc(16);
    crypto.randomFillSync(random);
    // 内容 是个对象,
    // 要转xml 字符串
    let xmlData = DataSynthesizer.xml(contentObj, GXH_ReplyCDATA);

    let msgBuf = Buffer.from(xmlData);
    // 要4个字节的 长度
    let msgLenBuf = Buffer.alloc(4);
    msgLenBuf.writeInt32BE(msgBuf.length);
    // 还有 appid
    let appIdBuf = Buffer.from(appId);

    // 合并buf
    let totalBuf = Buffer.concat([random, msgLenBuf, msgBuf, appIdBuf]);
    // 微信的  被加密度块  的 blockSize 是  32 ? 不是  16个字节???
    totalBuf = paddingAction(totalBuf);
    // 要加密了
    const key = Buffer.from(GZHConfig.AESKey + "=", "base64");
    // 提取前 16 字节作为 IV
    const iv = key.subarray(0, 16);

    let encrypt = CryptoJS.AES.encrypt(
        CryptoJS.lib.WordArray.create(totalBuf),
        CryptoJS.lib.WordArray.create(key),
        {
            iv: CryptoJS.lib.WordArray.create(iv),
            mode: CryptoJS.mode.CBC,
            // padding: CryptoJS.pad.Pkcs7,
            // 已经 手动 填充完了...
            padding: CryptoJS.pad.ZeroPadding,
        }
    );
    // 密文
    let finalEncrypt = encrypt.ciphertext.toString(CryptoJS.enc.Base64);
    // 时间戳
    let timeStamp = Math.floor(Date.now() / 1000);
    // 做签名
    let needSign = [GZHConfig.verifyToken, timeStamp, nonce, finalEncrypt].sort().join("");
    // 签名
    let msgSignature = crypto.createHash("sha1").update(needSign).digest("hex");

    let callBack = {
        // 加密的
        Encrypt: finalEncrypt,
        // 时间戳
        TimeStamp: timeStamp,
        // 随机串
        Nonce: nonce,
        // 签名
        MsgSignature: msgSignature,
    };

    let finalMessage = DataSynthesizer.xml(
        {
            xml: xmlWithCDATA(callBack),
        },
        GXH_ReplyCDATA
    );
    return finalMessage;
}

module.exports = {
    encode,
};
